#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

using namespace std;

class UdpServer
{
public:
    UdpServer(std::string ip, int port)
        : _sockfd(-1), _port(port), _ip(ip) {};

    bool InitServer()
    {
        // 创建套接字
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        { // 创建套接字失败
            std::cerr << "socket error" << std::endl;
            return false;
        }

        std::cout << "socket create success, sockfd: " << _sockfd << std::endl;

        struct sockaddr_in local;
        memset(&local, '\0', sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = inet_addr(_ip.c_str());

        if (bind(_sockfd, (struct sockaddr *)&local, sizeof(sockaddr)) < 0)
        {
            cout << "bind error!" << endl;
            return false;
        }
        cout << "bind success" << endl;
        return true;
    }

    void Start()
    {
#define SIZE 128
        char buffer[SIZE];
        for (;;)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t size = recvfrom(_sockfd, &buffer, sizeof(buffer) - 1, 0, (sockaddr *)&peer, &len);
            if (size > 0)
            {
                buffer[size] = '\0';
                int port = ntohs(peer.sin_port);
                string ip = inet_ntoa(peer.sin_addr);
                cout << ip << ":" << port << "#" << buffer << endl;
            }
            else
            {
                cerr << "recvfrom fail" << endl;
            }
        }
    }

    ~UdpServer()
    {
        if (_sockfd >= 0)
        {
            close(_sockfd);
        }
    };

    // void Start()
    // {
    //     for(;;)
    //     {
    //         struct sockaddr_in peer;
    //         memset(&peer, '\0', sizeof(peer));
    //         socklen_t len = sizeof(peer);
    //         int sock = accept(_listen_sock, (struct sockaddr*)&peer, &len);
    //         if(sock < 0)
    //         {
    //             cerr << "accept fail!" << endl;
    //             continue;
    //         }

    //         string client_ip = inet_ntoa(peer.sin_addr);
    //         int client_port = ntohs(peer.sin_port);
    //         cout << "get a new link->" << sock << "[" << client_ip << "]:" << client_port << endl;

    //         pid_t id = fork();//创建爸爸进程;
    //         if(id == 0)
    //         {
    //             close(_listen_sock);//关闭爷爷文件描述符;
    //             if(fork() > 0)
    //             {
    //                 exit(0);//爸爸进程退出;
    //             }

    //             Service(sock, client_ip, client_port);//孙子进程进行网络服务;
    //             exit(0);//孙子进程提供完服务退出.
    //         }
    //         close(sock); //关闭爸爸文件描述符;
    //         waitpid(id, nullptr, 0);//等待爸爸进程退出.
    //     }
    // }

    class Param
    {
    public:
        Param(int sock, std::string ip, int port)
            : _sock(sock), _ip(ip), _port(port)
        {
        }
        ~Param()
        {
        }

    public:
        int _sock;
        std::string _ip;
        int _port;
    };

    // static void* HandlerRequest(void* arg)
    // {
    //     pthread_detach(pthread_self());
    //     Param* p = (Param*)arg;

    //     Service(p->_sock, p->_ip, p->_port);

    //     delete p;//析构参数申请的堆空间.
    //     return nullptr;
    // }

    // void Start()
    // {
    //     for(;;)
    //     {
    //         struct sockaddr_in peer;
    //         memset(&peer, '\0', sizeof(peer));
    //         socklen_t len = sizeof(peer);
    //         int sock = accept(_listen_sock, (struct sockaddr*)&peer, &len);
    //         if(sock < 0)
    //         {
    //             cerr << "accept fail!" << endl;
    //             continue;
    //         }

    //         string client_ip = inet_ntoa(peer.sin_addr);
    //         int client_port = ntohs(peer.sin_port);
    //         cout << "get a new link->" << sock << "[" << client_ip << "]:" << client_port << endl;

    //         Param* p = new Param(sock, client_ip, client_port);
    //         pthread_t tid;
    //         pthread_create(&tid, nullptr, HandlerRequest, p);
    //     }
    // }

private:
    int _sockfd; // 文件描述符
    int _port;
    std::string _ip;
};

#include <unordered_map>

class Handler
{
public:
    Handler()
    {}

    ~Handler()
    {}

    void operator()(int sock, std::string client_ip, int client_port)
    {
        unordered_map<string, string> dict;
        dict.insert(make_pair("hello", "你好"));
        dict.insert(make_pair("world", "世界"));
        dict.insert(make_pair("love", "爱"));

        char buffer[1024];
        string value;
        while(true)
        {
            size_t size = read(sock, buffer, sizeof(buffer)-1);
            if(size > 0)
            {
                buffer[size] = '\0';
                cout << client_ip << ":" << client_port << "#" << buffer << endl;

                string key = key;
                auto it = dict.find(key);
                if(it != dict.end())
                {
                    value = it->second;
                }
                else
                {
                    value = key;
                }
                write(sock, value.c_str(), value.size());
            }
            else if(size == 0)
            {
                cout << client_ip << ":" << client_port << "close!" << endl;
                break;
            }
            else
            {
                cerr << sock << "read fail!" << endl;
                break;
            }
        }
        close(sock);
        cout << client_ip << ":" << client_port << "Service done!" << endl;
    }
};

void* Routine(void* arg)
{
    pthread_detach(pthread_self());
    int sock = *(int*)arg;
    delete (int*)arg;

    while(true)
    {
        request_t rq;
        ssize_t size = recv(sock, &rq, sizeof(rq), 0);
        if(size > 0)
        {
            response_t rp = {0, 0};
            switch(rq.op)
            {
            case '+':
				rp.result = rq.x + rq.y;
				break;
			case '-':
				rp.result = rq.x - rq.y;
				break;
			case '*':
				rp.result = rq.x * rq.y;
				break;
			case '/':
				if (rq.y == 0)
                {
					rp.code = 1; //除0错误
				}
				else
                {
					rp.result = rq.x / rq.y;
				}
				break;
			case '%':
				if (rq.y == 0)
                {
					rp.code = 2; //模0错误
				}
				else
                {
					rp.result = rq.x % rq.y;
				}
				break;
			default:
				rp.code = 3; //非法运算
				break;
            }
            send(sock, &rp, sizeof(rp), 0);
        }
        else if(size == 0)
        {
            cout << "service done" << endl;
            break;
        }
        else
        {
            cout << "read error" << endl;
            break;
        }
    }
    close(sock);
    return nullptr;
}



int main(int argc, char* argv[])
{
	if (argc != 2)
    {
		cerr << "Usage: " << argv[0] << " port" << endl;
		exit(1);
	}
	int port = atoi(argv[1]);

	//创建套接字
	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (listen_sock < 0){
		cerr << "socket error!" << endl;
		exit(2);
	}

	//绑定
	struct sockaddr_in local;
	memset(&local, 0, sizeof(local));
	local.sin_family = AF_INET;
	local.sin_port = htons(port);
	local.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
		cerr << "bind error!" << endl;
		exit(3);
	}

	//监听
	if (listen(listen_sock, 5) < 0){
		cerr << "listen error!" << endl;
		exit(4);
	}

	//启动服务器
	struct sockaddr peer;
	memset(&peer, 0, sizeof(peer));
	for (;;)
    {
		socklen_t len = sizeof(peer);
		int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
		if (sock < 0){
			cerr << "accept error!" << endl;
			continue;
		}
		pthread_t tid = 0;
		int* p = new int(sock);
		pthread_create(&tid, nullptr, Routine, p);
	}
	return 0;
}

typedef struct request
{
    int x;//左操作数
    int y;//右操作数
    char op;//操作符
}request_t;


typedef struct response
{
    int code;//计算状态;
    int result;//计算结构;
}response_t;


int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        cerr << "Usag: " << argv[0] << "server_ip server_port" << endl;
        exit(1);
    }
    string server_ip = argv[1];
    int server_port = atoi(argv[2]);

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
    {
        cerr << "socket error!" << endl;
        exit(2);
    }

    struct sockaddr_in peer;
    memset(&peer, '\0', sizeof(peer));
    peer.sin_family = AF_INET;
    peer.sin_port = htons(server_port);
    peer.sin_addr.s_addr = inet_addr(server_ip.c_str());
    if(connect(sock, (struct sockaddr*)&peer, sizeof(peer)) < 0)
    {
        cerr << "connect failed!" << endl;
        exit(3);
    }

    while(true)
    {
        request_t rq;
		cout << "请输入左操作数# ";
		cin >> rq.x;
		cout << "请输入右操作数# ";
		cin >> rq.y;
		cout << "请输入需要进行的操作[+-*/%]# ";
		cin >> rq.op;
        send(sock, &rq, sizeof(rq), 0);
		
		//接收请求响应
		response_t rp;
		recv(sock, &rp, sizeof(rp), 0);
		cout << "status: " << rp.code << endl;
		cout << rq.x << rq.op << rq.y << "=" << rp.result << endl;
    }
    return 0;
}
